﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

namespace price.ro
{
    public class HTMLGrabSiProxyGen
    {
        ///Zona privata
        ///************
        #region Clase locale
        /// <summary>
        /// Tine minte proxy-urile folosite si ultima oara cand au fost ele folosite. Daca trece un timp x ele pot fi refolosite (daca mai sunt functionale:)) )
        /// </summary>
        private class used
        {
            public string Proxy { get; set; }
            public DateTime Data { get; set; }
            public int Rapiditate { get; set; }
            public bool ProxyCuInterfata { get; set; }//asta nu e bun, pt ca trebuie sa ii trimiti linku ca parametru
        }
        #endregion

        #region Variabile locale
        private static List<used> usedProxies { get; set; }
        private static Semaphore S { get; set; }
        private static int NrSemafor { get; set; }
        private static int MaxThreads { get; set; }
        private static int SecundeTimeout { get; set; }
        private static int PingMiliSecTimeout { get; set; }
        private static int DurataViataProxy { get; set; }
        private static string CurrentProxy { get; set; }
        private static string Director { get; set; }
        private static string CaleFisierGoodProxies { get; set; }
        #endregion

        #region Functii Semafoare si Threads si GetDirector
        public static void WaitSemaphore(int SecundeTimeout) 
        {
            bool b = false;
            while (!b)
            {
                lock (S) { b = S.WaitOne(SecundeTimeout * 1000); }
                if (!b) Thread.Sleep(500);
            }
        }
        public static void WaitSemaphore() { WaitSemaphore(HTMLGrabSiProxyGen.SecundeTimeout); }
        public static void ReleaseSemaphore() 
        {
            lock (S) { NrSemafor = S.Release(); while (NrSemafor == 0) Thread.Sleep(500); }
        }
        public static int GetSecundeTimeout() { return HTMLGrabSiProxyGen.SecundeTimeout; }
        public static int GetMaxThreads() { return HTMLGrabSiProxyGen.MaxThreads; }
        public static void SetMaxThreads(int MaxThreads) { HTMLGrabSiProxyGen.MaxThreads = MaxThreads; }
        public static string GetDirector() { return HTMLGrabSiProxyGen.Director + "\\"; }
        #endregion

        #region Functii RenewProxy
        private static void IncarcaGoodProxiesVechi(string path)
        {
            string rez=String.Empty;
            int indexRapiditate=100;//proxy-urile au fost ordonate crescator dupa Rapiditate (daca fisieru e generat de prog asta)

            if (File.Exists(path))
                rez = File.ReadAllText(path);
            foreach (var v in rez.Split('\n'))
                if (v.Length >= 10)
                {
                    Func<used, bool> fct = (used u) => u.Proxy == v.Trim(new char[] { '\n', '\r', '\t', ' ' });
                    if (usedProxies.Where(fct).Count() == 0)
                        usedProxies.Add(new used() { Proxy = v.Trim(new char[] { '\n', '\r', '\t', ' ' }), Data = DateTime.Now.AddYears(-1), Rapiditate = indexRapiditate++, ProxyCuInterfata = false });
                }
        }

        private static bool VerificaProxyOK(string proxyNou, int PingMiliSecTimeout, int DurataViataProxy)
        {
            Func<used, bool> fct = (used u) => u.Proxy == proxyNou && u.Data >= DateTime.Now.AddMinutes(-1 * DurataViataProxy);
            lock (usedProxies)
            {
                if (usedProxies.Where(fct).Count() == 0)
                {
                    Func<used, bool> f = (used u) => u.Proxy == proxyNou && u.ProxyCuInterfata;
                    if (usedProxies.Where(f).Count() == 0)
                    {
                        int Rapiditate = PingOk(proxyNou, PingMiliSecTimeout);
                        if (Rapiditate != -1)
                        {
                            Func<used, bool> fct2 = (used u) => u.Proxy == proxyNou;
                            if (usedProxies.Where(fct2).Count() == 1) usedProxies.Where(fct2).First().Data = DateTime.Now;
                            else usedProxies.Add(new used() { Proxy = proxyNou, Data = DateTime.Now, Rapiditate = Rapiditate, ProxyCuInterfata = false });
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        private static string RefolosesteProxyMaiVechi(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {
            var usdList = from v in HTMLGrabSiProxyGen.usedProxies where !v.ProxyCuInterfata && v.Data < DateTime.Now.AddMinutes(-1 * DurataViataProxy) orderby v.Rapiditate select v;
            foreach (var v in usdList)
                if (VerificaProxyOK(v.Proxy, PingMiliSecTimeout, DurataViataProxy)) { v.Data = DateTime.Now;  return v.Proxy; }
            return String.Empty;
        }

        private static string RenewProxySite8(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {
            string[] tariSimpatice = new string[] { "Romania", "Bulgaria", "Hungary‎", "Serbia", "Moldova", "Ukraine‎", "Russian Federation", "Turkey", "Greece", "Germany‎", "France", "Italy", "Switzerland", "Finland" };

            string iaProxy;
            while ((iaProxy = Grab("http://www.ip-adress.com/Proxy_Checker/index.php", false, "", SecundeTimeout)) == String.Empty) ;
            int index1 = iaProxy.IndexOf("<tr class=\"yellow\">");
            string proxyTemp = String.Empty;
            while (index1 != -1)
            {
                string proxyNou = iaProxy.Substring(iaProxy.IndexOf("<td>", index1) + 4, iaProxy.IndexOf("</td>", index1) - (iaProxy.IndexOf("<td>", index1) + 4));

                int i1 = iaProxy.IndexOf("<td>", index1) + 4;
                int i2 = iaProxy.IndexOf("<td>", i1) + 4;
                int i3 = iaProxy.IndexOf("<td>", i2) + 4;
                string tara = iaProxy.Substring(i3, iaProxy.IndexOf("</td>", i3) - i3);
                if (tariSimpatice.Contains<string>(tara))
                    if (VerificaProxyOK(proxyNou, PingMiliSecTimeout, DurataViataProxy)) return proxyNou;
                else proxyTemp = proxyNou;

                index1 = iaProxy.IndexOf("<tr class=\"yellow\">", i3);
            }

            if (VerificaProxyOK(proxyTemp, PingMiliSecTimeout, DurataViataProxy)) return proxyTemp;
            return String.Empty;
        }

        private static string RenewProxySite7(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {
            string iaProxy;
            while ((iaProxy = Grab("http://aliveproxy.com/fastest-proxies/", false, "", SecundeTimeout)) == String.Empty) ;
            int index1 = iaProxy.IndexOf("Smart<br>traceroute");
            while (index1 != -1)
            {
                int index2 = iaProxy.IndexOf("<td  class=\"dt-tb2\" >", index1);
                string proxyNou = iaProxy.Substring(index2 + "<td  class=\"dt-tb2\" >".Length, iaProxy.IndexOf("<br>", index2) - (index2 + "<td  class=\"dt-tb2\" >".Length));
                for (int i = 0; i < 6; i++) index2 = iaProxy.IndexOf("<td  class=\"dt-tb2\" >", index2 + 10);
                string Ping = iaProxy.Substring(index2 + "<td  class=\"dt-tb2\" >".Length, iaProxy.IndexOf("</td>", index2) - (index2 + "<td  class=\"dt-tb2\" >".Length));
                if (int.Parse(Ping) < 600)
                { for (int i = 0; i < 4; i++) index2 = iaProxy.IndexOf("<td  class=\"dt-tb2\" >", index2 + 10); index1 = index2; }
                else
                    if (VerificaProxyOK(proxyNou, PingMiliSecTimeout, DurataViataProxy)) return proxyNou;
            }
            return String.Empty;
        }

        private static string RenewProxySite6(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {
            string iaProxy;
            while ((iaProxy = Grab("http://proxyipchecker.com/", false, "", SecundeTimeout)) == String.Empty) ;
            int index1 = iaProxy.IndexOf("<ul class=\"freshproxies\">");
            string tip1="<li class=\"fast highbw\">";
            string tip2="<li class=\"fast medbw\">";
            string tip3="<li class=\"veryfast lowbw\">";
            string tip4="<li class=\"veryfast highbw\">";
            char[] trim = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' ' };
            while (index1 != -1)
            {
                int index2 = Math.Min(iaProxy.IndexOf(tip1) + tip1.Length, Math.Min(iaProxy.IndexOf(tip2) + tip2.Length, Math.Min(iaProxy.IndexOf(tip3) + tip3.Length, iaProxy.IndexOf(tip4) + tip4.Length)));
                int index3 = iaProxy.IndexOf("</li>", index2);
                string proxyNou = iaProxy.Substring(index2, index3 - index2).ToLower().Trim(trim);
                proxyNou = proxyNou.Substring(0, proxyNou.IndexOf(":") - 1) + ":" + proxyNou.Substring(proxyNou.IndexOf(":") + 2);

                if (VerificaProxyOK(proxyNou, PingMiliSecTimeout, DurataViataProxy)) return proxyNou;

                if (index1 == index3) break;
                index1 = index3;
            }
            return String.Empty;
        }

        private static string RenewProxySite5(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {//MULTUMESC WIRESHARK!!!
            string iaProxy;
            while ((iaProxy = Grab("http://www.hidemyass.com/proxy-list/search-285444/__utm.gif?utmwv=5.2.6&utms=5&utmn=1038865803&utmhn=www.hidemyass.com&utmcs=utf-8&utmsr=1280x800&utmvp=1276x655&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=11.0%20r1&utmdt=Free%20Proxy%20List%20-%20Public%20Proxy%20Servers%20(IP%20PORT)%20-%20Hide%20My%20Ass!%20-%20Custom%20search%20%23285444&utmhid=454772712&utmr=0&utmp=%2Fproxy-list%2Fsearch-285444&utmac=UA-950416-6&utmcc=__utma%3D177890234.173441564.1333116266.1333116266.1333116266.1%3B%2B__utmz%3D177890234.1333116266.1.1.utmcsr%3D(direct)%7Cutmccn%3D(direct)%7Cutmcmd%3D(none)%3B&utmu=qB~", false, "", SecundeTimeout)) == String.Empty) ;
            int index1 = iaProxy.IndexOf("<span class=\"updatets \">");
            while (index1 != -1)
            {
                int index2 = iaProxy.IndexOf("<td>", index1) + 4;
                int index3 = iaProxy.IndexOf("</td>", index2);
                string proxyNou = NisteJegosi(iaProxy.Substring(index2, index3 - index2));
                string port = HtmlRemoval.StripTagsCharArray(iaProxy.Substring(index3, 40)).Trim(new char[] { '\r', '\n', '\t', ' ' });
                proxyNou = proxyNou + ":" + port;

                if (VerificaProxyOK(proxyNou, PingMiliSecTimeout, DurataViataProxy)) return proxyNou;

                index1 = index1 = iaProxy.IndexOf("<span class=\"updatets \">",index3+40);
            }
            return String.Empty;
        }
        /// <summary>
        /// Idiotii imi baga spanuri si divuri cu display:none ca sa nu pot face crawlink cica...:))
        /// </summary>
        private static string NisteJegosi(string jeg)
        {
            while (jeg.Contains("display:none"))
            {
                int index1 = jeg.IndexOf("style=\"display:none\">") + "style=\"display:none\">".Length;
                int index2 = jeg.IndexOf("</div>", index1); if ((index2 > jeg.IndexOf("</span>", index1) || index2 == -1) && jeg.IndexOf("</span>", index1) != -1) index2 = jeg.IndexOf("</span>", index1);
                jeg = jeg.Remove(index1, index2 - index1);
                jeg = jeg.Remove(index1 - "style=\"display:none\">".Length, "style=\"display:none\"".Length);
            }
            return HtmlRemoval.StripTagsCharArray(jeg);
        }

        private static string RenewProxySite4(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {
            string result=String.Empty;
            for (byte i = 0; i <= 3; i++)
                if (result == String.Empty) result = RenewProxySitePagina4(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy, i);
                else break;
            return result;
        }
        private static string RenewProxySitePagina4(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy, int Pagina)
        {
            string iaProxy;
            while ((iaProxy = Grab("http://spys.ru/en/free-proxy-list/"+Pagina.ToString()+"/", false, "", SecundeTimeout)) == String.Empty) ;
            int index1 = iaProxy.IndexOf("<font class=spy14>") + "<font class=spy14>".Length;
            while (index1 != -1)
            {
                int index2 = iaProxy.IndexOf("<font class=spy14>", index1) + "<font class=spy14>".Length;
                int index3 = iaProxy.IndexOf("<script type=\"text/javascript\">", index2);
                string proxyNou = iaProxy.Substring(index2, index3 - index2);
                int index4=iaProxy.IndexOf("<\\/font>\"+",index3)+"<\\/font>\"+".Length;
                int index5=iaProxy.IndexOf(")</script>",index4);
                string port = iaProxy.Substring(index4, index5 - index4).Replace("(", "").Replace(")", "").ToLower();
                string[] aux = port.Split(new char[] { '+' });
                if (aux.Length == 4) if (aux[0] == aux[2] && aux[1] == aux[3]) port = "8080";
                    else if (aux[0] != aux[1] && aux[0] != aux[2] && aux[0] != aux[3] && aux[1] != aux[2] && aux[1] != aux[3] && aux[2] != aux[3]) port = "3128";
                    else if (aux[0] == aux[1] && aux[1] == aux[2] && aux[2] == aux[3]) port = "8888";
                    else goto NotGood;
                else if (aux.Length == 3 && aux[0] == aux[2] && aux[1] != aux[2]) port = "808";
                else if (aux.Length == 2 && aux[0] != aux[1]) port = "80";
                else port = "8080";

                proxyNou = proxyNou + ":" + port;

                if (VerificaProxyOK(proxyNou, PingMiliSecTimeout, DurataViataProxy)) return proxyNou;

            NotGood:
                index1 = iaProxy.IndexOf("<font class=spy14>", index5) + "<font class=spy14>".Length;
                index1=iaProxy.IndexOf("<font class=spy14>", index1) + "<font class=spy14>".Length;
            }
            return String.Empty;
        }

        private static string RenewProxySite3(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {
            string iaProxy;
            while ((iaProxy = Grab("http://tools.rosinstrument.com/proxy/l100.xml", false, "", SecundeTimeout)) == String.Empty) ;
            int index1 = iaProxy.IndexOf("<item>\n<title>") + "<item>\n<title>".Length;
            while (index1 != -1)
            {
                int index2 = iaProxy.IndexOf("</title>", index1);
                string proxyNou = iaProxy.Substring(index1, index2 - index1);
                string port=proxyNou.Substring(proxyNou.IndexOf(":")+1);
                proxyNou = RezolvaDomeniu(proxyNou.Substring(0, proxyNou.IndexOf(":")), SecundeTimeout);
                proxyNou += ":" + port;

                if (VerificaProxyOK(proxyNou, PingMiliSecTimeout, DurataViataProxy)) return proxyNou;

                index1 = iaProxy.IndexOf("<item>\n<title>", index2) + "<item>\n<title>".Length;
            }
            return String.Empty;
        }

        private static string RenewProxySite2(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {
            string result = String.Empty;
            for (short i = 1; i <= 7; i++)
                if (result == String.Empty) result = RenewProxySitePagina2(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy, i);
                else break;
            return result;
        }
        private static string RenewProxySitePagina2(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy, int Pagina)
        {
            string iaProxy;
            while ((iaProxy = Grab("http://www.publicproxyservers.com/proxy/list" + Pagina.ToString() + ".html", false, "", SecundeTimeout)) == String.Empty) ;
            int index1 = iaProxy.IndexOf("<td class=\"pthtdd\"><a target=\"_blank\" href=\"http://") + "<td class=\"pthtdd\"><a target=\"_blank\" href=\"http://".Length;
            while (index1 != -1)
            {
                int index2 = iaProxy.IndexOf("\">", index1);
                string proxyNou = iaProxy.Substring(index1, index2 - index1).Replace("/", "");
                proxyNou = RezolvaDomeniu(proxyNou, SecundeTimeout);
                proxyNou += ":80";

                if (VerificaProxyOK(proxyNou, PingMiliSecTimeout, DurataViataProxy)) return proxyNou;

                index1 = iaProxy.IndexOf("<td class=\"pthtdd\"><a target=\"_blank\" href=\"http://", index2) + "<td class=\"pthtdd\"><a target=\"_blank\" href=\"http://".Length;
            }
            return String.Empty;
        }

        private static string RenewProxySite1(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {
            string result = String.Empty;
            for (short i = 0; i <= 3000; i += 25)
                if (result == String.Empty) result = RenewProxySitePagina1(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy, i);
                else break;
            return result;
        }
        private static string RenewProxySitePagina1(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy, int Pagina)
        {
            string iaProxy;
            while ((iaProxy = Grab("http://www.proxyserverlist.org/popular-proxies.php?start=" + Pagina.ToString() + "/", false, "", SecundeTimeout)) == String.Empty) ;
            int index1 = iaProxy.IndexOf("target=\"_blank\" rel=\"nofollow\">") + "target=\"_blank\" rel=\"nofollow\">".Length;
            while (index1 != -1)
            {
                int index2 = iaProxy.IndexOf("</div>", index1);
                string proxyNou = iaProxy.Substring(index1, index2 - index1).Replace("http://", "").Replace("/", "");
                proxyNou = RezolvaDomeniu(proxyNou, SecundeTimeout);
                proxyNou += ":80";

                if (VerificaProxyOK(proxyNou, PingMiliSecTimeout, DurataViataProxy)) return proxyNou;

                index1 = iaProxy.IndexOf("target=\"_blank\" rel=\"nofollow\">", index2) + "target=\"_blank\" rel=\"nofollow\">".Length;
            }
            return String.Empty;
        }

        private static string RenewProxySite0(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {
            string[] VeryFastButNotChecked = new string[] { "98.109.199.166:3128", "62.240.171.70:8080", "89.28.122.140:8081", "187.11.237.196:3128", "98.109.199.166:3128", "91.215.54.24:8080", "85.234.22.126:3128", "85.214.99.221:3128", "190.54.24.210:8080", "187.11.237.196:3128 ", "200.253.158.131:3128", "200.98.132.96:3128 ", "86.100.82.74:8080", "115.236.98.109:80", "190.90.36.8:8000", "173.14.37.125:80", "173.45.227.127:3128", "189.80.149.98:3128", "190.144.13.66:3128", "189.80.149.98:3128", "89.28.122.140:8081", "190.54.24.210:8080", "194.170.16.75:8080", "195.138.88.105:3128", "89.169.1.30:3128", "79.170.50.25:80" };

            foreach (var v in VeryFastButNotChecked)
            {
                if (VerificaProxyOK(v, PingMiliSecTimeout, DurataViataProxy)) return v;
            }
            return String.Empty;
        }
        #endregion

        #region Rezolva Domeniu
        private delegate IPHostEntry GetHostEntryHandler(string Domeniu);
        private static string RezolvaDomeniu(string Domeniu, int SecundeTimeout)
        {
            try
            {
                GetHostEntryHandler callback = new GetHostEntryHandler(Dns.GetHostEntry);
                IAsyncResult result = callback.BeginInvoke(Domeniu, null, null);
                if (result.AsyncWaitHandle.WaitOne((SecundeTimeout * 1000)/2, false))//nu vrem sa stam chiar cat stam pt un grab, ce dracu
                    return callback.EndInvoke(result).AddressList[0].ToString();
                else
                    return String.Empty;
            }
            catch (Exception)
            { return String.Empty; }
        }
        #endregion

        #region Face Ping si verifica Proxy-ul
        private static int PingOk(string proxy, int PingMiliSecTimeout)
        {
            Ping ping = new Ping();
            try
            {
                PingReply pingReply = ping.Send(proxy.Substring(0, proxy.IndexOf(":")), PingMiliSecTimeout, new byte[32], new PingOptions(128, true));
                if (!(pingReply == null))
                    if (pingReply.Status == IPStatus.Success)
                        return Convert.ToInt32(pingReply.RoundtripTime);
                    else pingReply = ping.Send(proxy.Substring(0, proxy.IndexOf(":")), PingMiliSecTimeout, new byte[32], new PingOptions(128, true));
                if (!(pingReply == null))
                    if (pingReply.Status == IPStatus.Success)
                        return Convert.ToInt32(pingReply.RoundtripTime); ;
            }
            catch { return -1; }
            return -1;
        }
        #endregion

        ///Zona publica
        ///************
        #region Constructori
        /// <summary>
        /// Initializeaza clasa asta
        /// </summary>
        /// <param name="MaxThreads">Nr maxim de Threaduri pe care le dorim simultan (default 20)</param>
        /// <param name="SecundeTimeout">Nr de secunde asteptate pana cand da Timeout cand face Grab (default 6)</param>
        /// <param name="PingMiliSecTimeout">Nr de milisecunde asteptate pana cand da Timeout cand face Ping (default 600)</param>
        /// <param name="DurataViataProxy">Nr de minute care trebuie asteptat pt ca un proxy sa poata fi folosit again (default 30)</param>
        /// <param name="Director">Cale catre directorul executiei curente</param>
        /// <param name="CaleFisierGoodProxies">Cale catre fisier cu proxy-uri bune de forma [ip:port]\r\n[ip:port]... (default goodProxies.txt)</param>
        public HTMLGrabSiProxyGen(int MaxThreads, int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy, string Director,string CaleFisierGoodProxies)
        {
            HTMLGrabSiProxyGen.usedProxies = new List<used>();
            HTMLGrabSiProxyGen.S = new Semaphore(MaxThreads / 2, MaxThreads);
            HTMLGrabSiProxyGen.MaxThreads = MaxThreads;
            HTMLGrabSiProxyGen.SecundeTimeout = SecundeTimeout;
            HTMLGrabSiProxyGen.PingMiliSecTimeout = PingMiliSecTimeout;
            HTMLGrabSiProxyGen.DurataViataProxy = DurataViataProxy;
            HTMLGrabSiProxyGen.CurrentProxy = String.Empty;
            HTMLGrabSiProxyGen.Director = Director;
            if (Directory.Exists(Director)) Directory.Delete(Director, true);
            Directory.CreateDirectory(Director);
            IncarcaGoodProxiesVechi(HTMLGrabSiProxyGen.CaleFisierGoodProxies = CaleFisierGoodProxies);
            _handler += new EventHandler(Handler);
            SetConsoleCtrlHandler(_handler, true);
        }
        /// <summary>
        /// Initializeaza clasa asta
        /// </summary>
        /// <param name="MaxThreads">Nr maxim de Threaduri pe care le dorim simultan (default 20)</param>
        /// <param name="SecundeTimeout">Nr de secunde asteptate pana cand da Timeout cand face Grab (default 6)</param>
        /// <param name="PingMiliSecTimeout">Nr de milisecunde asteptate pana cand da Timeout cand face Ping (default 600)</param>
        /// <param name="DurataViataProxy">Nr de minute care trebuie asteptat pt ca un proxy sa poata fi folosit again (default 30)</param>
        /// <param name="Director">Cale catre directorul executiei curente</param>
        /// /// <param name="CaleFisierGoodProxies">Cale catre fisier cu proxy-uri bune de forma [ip:port]\r\n[ip:port]... (default goodProxies.txt)</param>
        public HTMLGrabSiProxyGen()
        {
            HTMLGrabSiProxyGen.usedProxies = new List<used>();
            HTMLGrabSiProxyGen.S = new Semaphore(20 / 2, 20);
            HTMLGrabSiProxyGen.MaxThreads = 20;
            HTMLGrabSiProxyGen.SecundeTimeout = 6;
            HTMLGrabSiProxyGen.PingMiliSecTimeout = 600;
            HTMLGrabSiProxyGen.DurataViataProxy = 30;
            HTMLGrabSiProxyGen.CurrentProxy = String.Empty;
            HTMLGrabSiProxyGen.Director = DateTime.Now.ToString("dd.MM.yyyy HH-mm-ss");
            if (Directory.Exists(Director)) Directory.Delete(Director, true);
            Directory.CreateDirectory(Director);
            IncarcaGoodProxiesVechi(HTMLGrabSiProxyGen.CaleFisierGoodProxies = "goodProxies.txt");
            _handler += new EventHandler(Handler);
            SetConsoleCtrlHandler(_handler, true);
        }
        #endregion

        #region Grab HTML
        /// <summary>
        /// Ia html de pe site-uri folosind un proxy si avand un Timeout
        /// </summary>
        /// <param name="link">Link-ul site-ului</param>
        /// <param name="UseProxy">Daca folosim sau nu proxy. Daca e false, urm argument e ignorat</param>
        /// <param name="Proxy">Proxy-ul de forma [ip/site]:[port]</param>
        /// <param name="SecundeTimeout">Cat suntem dispusi sa asteptam dupa proxy-u asta sa ia html-ul (in secunde)</param>
        /// <returns>Returneaza string cu htmlul</returns>
        public static string Grab(string link, bool UseProxy, string Proxy, int SecundeTimeout)
        {
            Console.WriteLine("Grab " + link.Substring(0, link.Length > 50 ? 50 : link.Length) + " " + DateTime.Now.ToString("HH:mm:ss"));//--
            StringBuilder sb = new StringBuilder();
            byte[] buf = new byte[8192];
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link);
            //asa l-am pacalit in sfarsit!!!
            request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5";
            if (UseProxy) request.Proxy = new WebProxy(Proxy);
            request.Timeout = SecundeTimeout * 1000;//x sec

            MaiIncearcaAltProxy:
            HttpWebResponse response;
            try { response = (HttpWebResponse)request.GetResponse(); }
            catch (Exception ex)
            {
                File.AppendAllText(HTMLGrabSiProxyGen.GetDirector() + "logs.txt", ex.Message + "\t proxy: " + Proxy + "\t not done: " + link + "\t" + DateTime.Now.ToString("HH:mm:ss") + "\r\n");
                if (ex.Message.Contains("timed out") || ex.Message.Contains("403")) { HTMLGrabSiProxyGen.GenerateProxy(); }
                if (ex.Message.Contains("407") || ex.Message.Contains("404")) { HTMLGrabSiProxyGen.ProxyCuInterfata(); HTMLGrabSiProxyGen.GenerateProxy(); }
                goto MaiIncearcaAltProxy;
            }//cel mai probabil timeout-ul nu a fost indeplinit

            MaiIncearcaOdata:
            Stream resStream = response.GetResponseStream();
            string tempString = null;
            int count = 0;
            try
            {
                do
                {
                    count = resStream.Read(buf, 0, buf.Length);
                    if (count != 0)
                    {
                        tempString = Encoding.ASCII.GetString(buf, 0, count);
                        sb.Append(tempString);
                    }
                }
                while (count > 0);
            }
            catch { goto MaiIncearcaOdata; }
            return sb.ToString();
        }
        /// <summary>
        /// Ia html de pe site-uri folosind un proxy
        /// </summary>
        /// <param name="link">Link-ul site-ului</param>
        /// <param name="UseProxy">Daca folosim sau nu proxy. Daca e false, urm argument e ignorat</param>
        /// <param name="Proxy">Proxy-ul de forma [ip/site]:[port]</param>
        /// <returns>Returneaza string cu htmlul</returns>
        public static string Grab(string link, bool UseProxy, string Proxy)
        { return Grab(link, UseProxy, Proxy, HTMLGrabSiProxyGen.SecundeTimeout); }
        /// <summary>
        /// Ia html de pe site-uri folosind proxy-ul generat de HTMLGrabSiProxyGen
        /// </summary>
        /// <param name="link">Link-ul site-ului</param>
        /// <param name="UseProxy">Daca folosim sau nu proxy</param>
        /// <returns>Returneaza string cu htmlul</returns>
        public static string Grab(string link, bool UseProxy)
        { return Grab(link, UseProxy, HTMLGrabSiProxyGen.CurrentProxy, HTMLGrabSiProxyGen.SecundeTimeout); }
        /// <summary>
        /// Ia html de pe site-uri
        /// </summary>
        /// <param name="link">Link-ul site-ului</param>
        /// <returns>Returneaza string cu htmlul</returns>
        public static string Grab(string link)
        { return Grab(link, false, "", HTMLGrabSiProxyGen.SecundeTimeout); }
        #endregion

        #region Generate Proxy nou
        /// <summary>
        /// Proxy cu interfata, singura modalitate de a-l folosi e sa ii trimiti linku ca parametru :(
        /// </summary>
        public static void ProxyCuInterfata()
        {
            lock (HTMLGrabSiProxyGen.usedProxies)
            {
                Func<used, bool> f = (used u) => u.Proxy == HTMLGrabSiProxyGen.CurrentProxy;
                var prox = HTMLGrabSiProxyGen.usedProxies.Where(f);
                if (prox.Count() == 1) prox.First().ProxyCuInterfata = true;
            }
            GenerateProxy();
        }
        /// <summary>
        /// Imi genereaza un nou proxy din multe liste de proxiuri
        /// </summary>
        /// <param name="SecundeTimeout">Nr de secunde asteptate pana cand da Timeout cand face Grab (default 3)</param>
        /// <param name="PingMiliSecTimeout">Nr de milisecunde asteptate pana cand da Timeout cand face Ping (default 500)</param>
        /// <param name="DurataViataProxy">Nr de minute care trebuie asteptat pt ca un proxy sa poata fi folosit again (default 30)</param>
        /// <returns>un proxy de forma [site/ip]:[port]</returns>
        public static string GenerateProxy(int SecundeTimeout, int PingMiliSecTimeout, int DurataViataProxy)
        {
            string proxy = String.Empty;
            if (proxy == String.Empty) { proxy = RefolosesteProxyMaiVechi(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy); Console.WriteLine("RefolosesteProxyMaiVechi " + proxy + " " + DateTime.Now.ToString("HH:mm:ss")); }//--
            //proxy-urile astea sunt cam futute
            if (proxy == String.Empty) { proxy = RenewProxySite0(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy); Console.WriteLine("GenerateProxySite 0 " + proxy + " " + DateTime.Now.ToString("HH:mm:ss")); }//--
            //if (proxy == String.Empty) { proxy = RenewProxySite1(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy); Console.WriteLine("GenerateProxySite 1 " + proxy + " " + DateTime.Now.ToString("HH:mm:ss")); }//--
            //if (proxy == String.Empty) { proxy = RenewProxySite2(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy); Console.WriteLine("GenerateProxySite 2 " + proxy + " " + DateTime.Now.ToString("HH:mm:ss")); }//--
            //if (proxy == String.Empty) { proxy = RenewProxySite3(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy); Console.WriteLine("GenerateProxySite 3 " + proxy + " " + DateTime.Now.ToString("HH:mm:ss")); }//--
            if (proxy == String.Empty) { proxy = RenewProxySite4(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy); Console.WriteLine("GenerateProxySite 4 " + proxy + " " + DateTime.Now.ToString("HH:mm:ss")); }//--
            if (proxy == String.Empty) { proxy = RenewProxySite5(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy); Console.WriteLine("GenerateProxySite 5 " + proxy + " " + DateTime.Now.ToString("HH:mm:ss")); }//--
            if (proxy == String.Empty) { proxy = RenewProxySite6(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy); Console.WriteLine("GenerateProxySite 6 " + proxy + " " + DateTime.Now.ToString("HH:mm:ss")); }//--
            if (proxy == String.Empty) { proxy = RenewProxySite7(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy); Console.WriteLine("GenerateProxySite 7 " + proxy + " " + DateTime.Now.ToString("HH:mm:ss")); }//--
            if (proxy == String.Empty) { proxy = RenewProxySite8(SecundeTimeout, PingMiliSecTimeout, DurataViataProxy); Console.WriteLine("GenerateProxySite 8 " + proxy + " " + DateTime.Now.ToString("HH:mm:ss")); }//--
            if (proxy != String.Empty) lock (HTMLGrabSiProxyGen.CurrentProxy) { HTMLGrabSiProxyGen.CurrentProxy = proxy; }
            return proxy;
        }
        /// <summary>
        /// Imi genereaza un nou proxy din multe liste de proxiuri
        /// </summary>
        /// <param name="SecundeTimeout">Nr de secunde asteptate pana cand da Timeout cand face Grab</param>
        /// <param name="PingMiliSecTimeout">Nr de milisecunde asteptate pana cand da Timeout cand face Ping</param>
        /// <param name="DurataViataProxy">Nr de minute care trebuie asteptat pt ca un proxy sa poata fi folosit again</param>
        /// <returns>un proxy de forma [site/ip]:[port]</returns>
        public static string GenerateProxy()
        {
            return GenerateProxy(HTMLGrabSiProxyGen.SecundeTimeout, HTMLGrabSiProxyGen.PingMiliSecTimeout, HTMLGrabSiProxyGen.DurataViataProxy);
        }
        #endregion

        #region Print Good Proxies
        /// <summary>
        /// Returneaza o lista de proxiuri despartite prin \r\n
        /// </summary>
        /// <returns>Returneaza o lista de proxiuri despartite prin \r\n</returns>
        private static string Afis()
        {
            string rez = String.Empty;
            var query = (from v in HTMLGrabSiProxyGen.usedProxies where !v.ProxyCuInterfata&&v.Proxy.Length>10 orderby v.Rapiditate select v.Proxy).Distinct();
            foreach (var v in query)
                rez += v + "\r\n";
            return rez;
        }
        #endregion

        #region Zona in care scriu in fisier proxy-urile bune ('trigger' automat ce porneste la inchiderea programului)
        [DllImport("Kernel32")]
        private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);

        private delegate bool EventHandler(CtrlType sig);
        static EventHandler _handler;

        enum CtrlType { CTRL_C_EVENT = 0, CTRL_BREAK_EVENT = 1, CTRL_CLOSE_EVENT = 2, CTRL_LOGOFF_EVENT = 5, CTRL_SHUTDOWN_EVENT = 6 }
        private static bool Handler(CtrlType sig)
        {
            /*switch (sig)
            {
                case CtrlType.CTRL_SHUTDOWN_EVENT:
                case CtrlType.CTRL_CLOSE_EVENT: 
                default: 
            }*/
            if (File.Exists(HTMLGrabSiProxyGen.CaleFisierGoodProxies)) File.Copy(HTMLGrabSiProxyGen.CaleFisierGoodProxies, "_old" + HTMLGrabSiProxyGen.CaleFisierGoodProxies, true);
            if (File.Exists(HTMLGrabSiProxyGen.CaleFisierGoodProxies)) File.Delete(HTMLGrabSiProxyGen.CaleFisierGoodProxies);
            File.AppendAllText(HTMLGrabSiProxyGen.CaleFisierGoodProxies, HTMLGrabSiProxyGen.Afis());
            File.AppendAllText(HTMLGrabSiProxyGen.GetDirector() + HTMLGrabSiProxyGen.CaleFisierGoodProxies, HTMLGrabSiProxyGen.Afis());
            return false;
        }
        #endregion
    }

    #region Clase pt MultiThreading
    /// <summary>
    /// trimite threadului un obiect cu 3 linkuri(caracteristici,descriere,pareri) si un proxy care sa ia html-urile
    /// </summary>
    public class item
    {
        public string link1 { get; set; }
        public string link2 { get; set; }
        public string link3 { get; set; }
    }
    /// <summary>
    /// Imi trimite la threaduri obiecte ce contin un item si un AutoResetEvent
    /// </summary>
    public class ProdusTh
    {
        public item it { get; set; }
        public AutoResetEvent autoEvent { get; set; }
    }
    #endregion
}
